package lock;

import java.util.concurrent.locks.ReentrantLock;

/**
 * 自旋锁是一种特殊的锁机制，其基本思想是：当一个线程想要获取锁时，它会不断地尝试获取锁（“自旋”）而不是立即进入阻塞状态。
 * 自旋锁适用于临界区代码执行时间较短的场景，因为自旋操作本质上会浪费 CPU 时间。自旋锁的特点是，线程在等待锁的过程中不会进入休眠状态，而是会一直忙等，直到获得锁为止。
 *
 * 自旋锁的优点：
 *
 * 如果临界区代码执行时间很短，且锁竞争较少，自旋锁可以避免线程挂起和唤醒的开销。
 * 自旋锁对于线程之间竞争不激烈的场景，性能较好。
 * 自旋锁的缺点：
 *
 * 如果锁竞争激烈（即多个线程频繁地争夺锁），自旋锁可能导致 CPU 资源浪费，降低系统性能。
 * 如果自旋等待的时间过长，可能会造成系统性能下降，尤其是在高负载的情况下。
 * 自旋锁的实现方式
 * 在 Java 中，自旋锁通常通过 volatile 变量和 while 循环来模拟。自旋锁会不断地检查锁的状态，若未获取到锁，则继续自旋等待。
 *
 * 自旋锁示范代码
 * 我们可以通过 ReentrantLock 类的 tryLock 方法来模拟自旋锁，也可以手动使用 volatile 和 while 循环来实现一个简单的自旋锁。下面我们给出两种实现方式。
 *
 * 1. 使用 ReentrantLock 的 tryLock 方法模拟自旋锁
 */
public class SpinLockExample {
    private static final ReentrantLock lock = new ReentrantLock();

    private static int sharedResource = 0;

    public static void main(String[] args) {

         Thread thread1 = new Thread(() -> {
            while (true){
                if (lock.tryLock()){
                    try {
                        Thread.sleep(5000);
                        sharedResource++;
                        System.out.println("Thread 1 acquired the lock");
                        break;
                    } catch (InterruptedException e) {
                        lock.unlock();
                    } finally {
                        lock.unlock();
                    }
                }
            }
        });

        Thread thread2 = new Thread(() -> {
            while (true){
                if (lock.tryLock()){
                    try {
                        Thread.sleep(5000);
                        sharedResource++;
                        System.out.println("Thread 2 acquired the lock");
                        break;
                    }catch (InterruptedException e) {
                        lock.unlock();
                    }finally {
                        lock.unlock();
                    }
                }
            }
        });

        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("Final sharedResource value: " + sharedResource);


    }
}
